package org.zy.client;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import org.zy.core.Message;

public class ProxyHandler extends SimpleChannelInboundHandler<Message> {

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Message myMsg) {
        // 客户端读取代理服务器数据
        byte type = myMsg.getType();

        switch (type) {
            case Message.TYPE_HEARTBEAT:
                break;

            case Message.TYPE_CONNECT:
                // 连接到真实服务器
                System.out.println("连接到真实服务器");
                String connectVisitorId = new String(myMsg.getData());
                RealSocket.connectRealServer(connectVisitorId);
                break;

            case Message.TYPE_DISCONNECT:
                // 断开连接
                String disconnectVisitorId = new String(myMsg.getData());
                ClientChannelManager.removeVisitorAndClose(disconnectVisitorId);
                break;

            case Message.TYPE_TRANSFER:
                // 把数据发送到真实服务器
                System.out.println("读取代理服务器数据，发送到真实服务器");
                ByteBuf buf = ctx.alloc().buffer(myMsg.getData().length);
                buf.writeBytes(myMsg.getData());

                String transferVisitorId = ctx.channel().attr(ClientChannelManager.VISITOR_ID).get();
                Channel realChannel = ClientChannelManager.REAL_CHANNEL_MAP.get(transferVisitorId);
                if (null != realChannel) {
                    realChannel.writeAndFlush(buf);
                }
                break;
            default:
                // 数据错误
        }
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        String visitorId = ctx.channel().attr(ClientChannelManager.VISITOR_ID).get();
        if (visitorId == null || visitorId.length() == 0) {
            super.channelWritabilityChanged(ctx);
            return;
        }
        Channel realChannel = ClientChannelManager.REAL_CHANNEL_MAP.get(visitorId);
        if (realChannel != null) {
            realChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
        }

        super.channelWritabilityChanged(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String visitorId = ctx.channel().attr(ClientChannelManager.VISITOR_ID).get();
        if (visitorId == null || visitorId.length() == 0) {
            super.channelInactive(ctx);
            return;
        }

        Channel realChannel = ClientChannelManager.REAL_CHANNEL_MAP.get(visitorId);
        if (realChannel != null && realChannel.isActive()) {
            realChannel.close();
        }
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        cause.printStackTrace();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            switch (event.state()) {
                case READER_IDLE:
                    ctx.channel().close();
                    break;

                case WRITER_IDLE:
                    Message myMsg = new Message(Message.TYPE_HEARTBEAT);
                    ctx.channel().writeAndFlush(myMsg);
                    break;

                case ALL_IDLE:
                    break;
            }
        }
    }
}